home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / gcl-1.000 / gcl-1 / gcl-1.0 / c / sfasl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-07  |  15.0 KB  |  638 lines

  1.  
  2. /* 
  3. Copyright William Schelter. All rights reserved.
  4. There is a companion file rsym.c which is used to build
  5. a list of the external symbols in a COFF or A.OUT object file, for
  6. example saved_kcl.  These are loaded into kcl, and the
  7. linking is done directly inside kcl.  This saves a good 
  8. deal of time.   For example a tiny file foo.o with one definition
  9. can be loaded in .04 seconds.  This is much faster than
  10. previously possible in kcl.
  11. The function fasload from unixfasl.c is replaced by the fasload
  12. in this file.
  13. this file is included in unixfasl.c
  14. via #include "../c/sfasl.c" 
  15. */
  16.  
  17.  
  18. /* for testing in standalone manner define STAND
  19.  You may then compile this file cc -g -DSTAND -DDEBUG -I../hn
  20.  a.out /tmp/foo.o /public/gcl/unixport/saved_kcl /public/gcl/unixport/
  21.  will write a /tmp/sfasltest file
  22.  which you can use comp to compare with one produced by ld.
  23.  */
  24.  
  25. #define IN_SFASL
  26.  
  27. #ifdef STAND
  28. #include "config.h"
  29. #include <stdio.h>
  30. #include "mdefs.h"
  31.  
  32. #else
  33. #include "include.h"
  34. #undef S_DATA
  35. #endif
  36.  
  37. #ifdef SEPARATE_SFASL_FILE
  38. #include SEPARATE_SFASL_FILE
  39. #else
  40.  
  41. #include <varargs.h>
  42. #include "ext_sym.h"
  43. struct node * find_sym();
  44. int node_compare();
  45. char *malloc();
  46. char *the_start;
  47. char *bsearch();
  48.  
  49. struct reloc relocation_info;
  50. /* next 5 static after debug */
  51.  
  52. int debug;
  53.  
  54. #ifdef DEBUG
  55. #define debug sfasldebug
  56. int sfasldebug=0;
  57. #define dprintf(s,ar) if(debug) { printf(" ( s )",ar) ; fflush(stdout);}
  58. #define STAT
  59.  
  60. #else /* end debug */
  61. #define dprintf(s,ar) 
  62. #define STAT static
  63. #endif
  64.  
  65.  
  66. #define MAXPATHLEN 200
  67. #define PTABLE_EXTRA 20
  68.  
  69. STAT struct syment *symbol_table;
  70. STAT char *start_address;
  71. STAT char *my_string_table;
  72. STAT int extra_bss;
  73.  
  74. STAT char command[200];
  75. STAT char tmpfile1 [50]; 
  76.  
  77. #ifndef describe_sym
  78. #define describe_sym(a)
  79. #endif
  80.  
  81. #ifdef STAND
  82. #include "rel_stand.c"
  83. #endif
  84.  
  85.  
  86. #define TEMPSPACE 50000
  87. char tempspace[TEMPSPACE];
  88. char *bil;
  89. char 
  90. *temp_malloc(n)
  91. unsigned int n; 
  92. {char *val;
  93.  val=(char *) (4*((((int)bil)+4)/4));
  94.  bil=val+n;
  95.  if (bil < tempspace +TEMPSPACE)
  96.    return val;
  97.  else {bil=val; 
  98.  dprintf( having to use regular malloc for %d,n);
  99.  return malloc(n);}
  100. }
  101.  
  102. /* begin reloc_file */
  103. #include RELOC_FILE
  104.  
  105. /* end reloc_file */
  106.  
  107. /* free up space which is not allocated in tempspace */
  108.  
  109. #define TEMP_FREE(x) \
  110. if (((char *)x)> tempspace+TEMPSPACE || ((char *)x)< tempspace) \
  111.      free(x)
  112.  
  113. int
  114. fasload(faslfile)
  115. object faslfile;
  116. {       long fasl_vector_start;
  117.     struct filehdr fileheader;
  118. #ifdef COFF
  119.     struct scnhdr sectionheader;
  120.         struct scnhdr section[10];
  121.     struct aouthdr header;
  122. #endif
  123.     int textsize, datasize, bsssize,nsyms;
  124.     int string_size=0;
  125.  
  126.     object memory, data;
  127.     FILE *fp;
  128.     char filename[MAXPATHLEN];
  129.     int i;
  130.     int init_address=0;
  131. #ifndef STAND    
  132.     object *old_vs_base = vs_base;
  133.     object *old_vs_top = vs_top;
  134. #endif
  135.       bil=tempspace; /* reset tmp malloc */
  136.     extra_bss=0;
  137. #ifdef STAND
  138.     strcpy(filename,faslfile);
  139.     fp=fopen(filename,RDONLY);
  140. #else
  141.     coerce_to_filename(faslfile, filename);
  142.     faslfile = open_stream(faslfile, smm_input, Cnil, Kerror);
  143.     vs_push(faslfile);
  144.     fp = faslfile->sm.sm_fp;
  145. #endif    
  146.  
  147.     HEADER_SEEK(fp);
  148.     if(!fread((char *)&fileheader, sizeof(struct filehdr), 1, fp))
  149.       FEerror("Could not get the header",0,0);
  150.     nsyms = NSYMS(fileheader);
  151. #ifdef COFF
  152.  
  153. #ifdef AIX3
  154.     setup_for_aix_load();
  155. #endif    
  156.  
  157.     fread(&header,1,fileheader.f_opthdr,fp);
  158.  
  159.     fread(§ion[1],fileheader.f_nscns,sizeof (struct  scnhdr),fp);
  160.     textsize = section[TEXT_NSCN].s_size;
  161.     datasize = section[DATA_NSCN].s_size; 
  162.     if (strcmp(section[BSS_NSCN].s_name, ".bss") == 0)
  163.       bsssize=section[BSS_NSCN].s_size; 
  164.     else     bsssize=section[BSS_NSCN].s_size = 0;
  165. #endif
  166.  
  167. #ifdef BSD
  168.     textsize=fileheader.a_text;
  169.     datasize=fileheader.a_data;
  170.     bsssize=fileheader.a_bss;
  171. #endif
  172.     symbol_table =
  173.       (struct syment *) temp_malloc(sizeof(struct syment)*
  174.                     (unsigned int)nsyms);
  175.     fseek(fp,(int)( N_SYMOFF(fileheader)),  0);
  176.     {
  177.     for (i = 0;  i < nsyms;  i++)
  178.         {fread((char *)&symbol_table[i], SYMESZ, 1, fp);
  179.          dprintf( symbol table %d , i);
  180.          if (debug) describe_sym(i);
  181.          dprintf( at %d , &symbol_table[i]);
  182. #ifdef HPUX
  183.          symbol_table[i].n_un.n_strx = string_size;
  184.          dprintf(string_size %d, string_size);
  185.          string_size += symbol_table[i].n_length + 1;
  186.          fseek(fp,(int)symbol_table[i].n_length,1);
  187. #endif
  188.            }
  189.        }
  190. /*    
  191. on MP386
  192. The sizeof(struct syment) = 20, while only SYMESZ =18. So we had to read
  193. one at a time.
  194. fread((char *)symbol_table, SYMESZ*fileheader.f_nsyms,1,fp);
  195. */
  196.  
  197. #ifdef READ_IN_STRING_TABLE
  198.  
  199. my_string_table=READ_IN_STRING_TABLE(fp,string_size);
  200.  
  201. #else  
  202. #ifdef MUST_SEEK_TO_STROFF
  203.   fseek(fp,N_STROFF(fileheader),0);
  204. #endif    
  205.   {int ii=0;
  206.     if (!fread((char *)&ii,sizeof(int),1,fp))
  207.           {FEerror("The string table of this file did not have any length",0,
  208.            0);}
  209.         fseek(fp,-4,1);
  210.         /* at present the string table is located just after the symbols */
  211.         my_string_table=temp_malloc((unsigned int)ii);
  212.         dprintf( string table leng = %d, ii);
  213.  
  214.         if(ii!=fread(my_string_table,1,ii,fp))
  215.           FEerror("Could not read whole string table",0,0) ;
  216.     }
  217. #endif    
  218. #ifdef SEEK_TO_END_OFILE
  219. SEEK_TO_END_OFILE(fp);    
  220. #else    
  221.      while ((i = getc(fp)) == 0)
  222.         ;
  223.     ungetc(i, fp);
  224. #endif
  225.     
  226.     fasl_vector_start=ftell(fp);
  227.  
  228.    if (!((c_table.ptable) && *(c_table.ptable)))
  229.      build_symbol_table();
  230.  
  231. /* figure out if there is more bss space needed */
  232.     extra_bss=get_extra_bss(symbol_table,nsyms,datasize+textsize+bsssize,
  233.                 &init_address,bsssize);
  234.     
  235. /* allocate some memory */
  236. #ifndef STAND    
  237.     memory = alloc_object(t_cfdata);
  238.     memory->cfd.cfd_self = 0;
  239.     memory->cfd.cfd_start = 0;
  240.     memory->cfd.cfd_size = datasize+textsize+bsssize + extra_bss;
  241.     vs_push(memory);
  242.         the_start=start_address=        
  243.      memory->cfd.cfd_start =    
  244.      alloc_contblock(memory->cfd.cfd_size);
  245.  
  246. #else
  247.     the_start=start_address
  248.       = malloc(datasize+textsize+bsssize + extra_bss + 0x80000);
  249.     the_start=start_address= (char *)(
  250.        0x1000* ((((int)the_start + 0x70000) + 0x1000)/0x1000));
  251.     
  252. #endif
  253.  
  254.     dprintf( code size %d , datasize+textsize+bsssize + extra_bss);
  255.     if (fseek(fp,N_TXTOFF(fileheader) ,0) < 0)
  256.         FEerror("file seek error",0,0);
  257.     fread(the_start, textsize + datasize, 1, fp);
  258.     dprintf(read into memory text +data %d bytes, textsize + datasize);
  259. /* relocate the actual loaded text  */
  260.  
  261.         dprintf( the_start %x, the_start);
  262.  
  263.     /* record which symbols are used */
  264.   
  265. #ifdef SYM_USED
  266.   {int j=0;
  267.      for(j=1; j< BSS_NSCN ; j++)
  268.        { dprintf( relocating section %d \n,j);
  269.     if (section[j].s_nreloc) fseek(fp,section[j].s_relptr,0);
  270.         for(i=0; i < section[j].s_nreloc; i++)
  271.       { struct syment *sym;
  272.         fread(&relocation_info, RELSZ, 1, fp);
  273.         sym = & symbol_table[relocation_info.r_symndx];
  274.         if (TC_SYMBOL_P(sym))
  275.           SYM_USED(sym) = 1;
  276.         }}}
  277. #endif
  278.  
  279.  
  280.     /* this looks up symbols in c.ptable and also adds new externals to
  281.        that c.table */
  282.     relocate_symbols(NSYMS(fileheader));  
  283.     
  284. #ifdef COFF
  285.   {int j=0;
  286.      for(j=1; j< BSS_NSCN ; j++)
  287.        { dprintf( relocating section %d \n,j);
  288.     if (section[j].s_nreloc) fseek(fp,section[j].s_relptr,0);
  289.         for(i=0; i < section[j].s_nreloc; i++)
  290.       /* RELSZ = sizeof(relocation_info) */
  291.       {fread(&relocation_info, RELSZ, 1, fp);
  292.            dprintf(relocating %d,i);
  293.        relocate();};
  294.         }};
  295. #endif
  296. #ifdef BSD
  297.      fseek(fp,N_RELOFF(fileheader),0);
  298.     {int nrel = (fileheader.a_trsize/sizeof(struct reloc));
  299.      for (i=0; i < nrel; i++)
  300.        {fread((char *)&relocation_info, sizeof(struct reloc),
  301.             1, fp);
  302.           dprintf(relocating %d,i);
  303.           relocate();
  304.         }
  305.     }
  306. #ifdef N_DRELOFF
  307.      fseek (fp, N_DRELOFF(fileheader), 0);
  308. #endif
  309.      {int nrel = (fileheader.a_drsize/sizeof(struct reloc));
  310.       the_start += fileheader.a_text;
  311.      for (i=0; i < nrel; i++)
  312.  
  313.        {fread((char *)&relocation_info, sizeof(struct reloc),
  314.             1, fp);
  315.           dprintf(relocating %d,i);
  316.           relocate();
  317.         }
  318.        }
  319. #endif
  320.  
  321. /* end of relocation */
  322.        dprintf( END OF RELOCATION \n,0);
  323.        dprintf( invoking init function at %x, start_address)
  324.        dprintf( textsize is %x,textsize);
  325.        dprintf( datasize is %x,datasize);
  326.  
  327. /* read in the fasl vector */
  328.     fseek(fp,fasl_vector_start,0);
  329.         if (feof(fp))
  330.       {data=0;}
  331.          else{
  332.     data = read_fasl_vector(faslfile);
  333.     vs_push(data);
  334. #ifdef COFF
  335.        dprintf( read fasl now symbols %d , fileheader.f_nsyms);
  336. #endif
  337.     }
  338.     close_stream(faslfile, 1);    
  339.  
  340. /*
  341.  {
  342.     int fd;
  343.  
  344.     fd = creat ("xsgcl.bits", 0777);
  345.     write (fd, memory->cfd.cfd_start, textsize + datasize);
  346.     close (fd);
  347.  
  348.     fd = open ("xsl2.bits", 0);
  349.     read (fd, memory->cfd.cfd_start, memory->cfd.cfd_size);
  350.     close (fd);
  351.  }
  352. */
  353.  
  354. #ifndef STAND
  355.     TEMP_FREE(my_string_table);
  356.     TEMP_FREE(symbol_table);
  357.  
  358.  
  359. #ifdef CLEAR_CACHE
  360.     CLEAR_CACHE;
  361. #endif
  362.     call_init(init_address,memory,data);
  363.     
  364.         vs_base = old_vs_base;
  365.     vs_top = old_vs_top;
  366.        if(symbol_value(Vload_verbose)!=Cnil)
  367.         printf("start address -T %x ",memory->cfd.cfd_start);
  368.     return(memory->cfd.cfd_size);
  369. #endif
  370.     {FILE *out;
  371.      out=fopen("/tmp/sfasltest","w");
  372.      fwrite((char *)&fileheader, sizeof(struct filehdr), 1, out);
  373.      fwrite(start_address,sizeof(char),datasize+textsize,out);
  374.      fclose(out);}
  375.      printf("\n(start %x)\n",start_address);
  376.  
  377. }
  378.  
  379.            
  380. get_extra_bss(symbol_table,length,start,ptr,bsssize)
  381. int length,bsssize;
  382. struct syment *symbol_table;
  383. int *ptr;   /* store init address offset here */
  384. {int result = start;
  385.  int next_bss =  start - bsssize;
  386.  struct syment *end,*sym;
  387.  char tem[SYMNMLEN +1];
  388.  end =symbol_table + length;
  389.  for(sym=symbol_table; sym < end; sym++)
  390.    {
  391.      
  392. #ifdef FIND_INIT
  393. FIND_INIT
  394. #endif
  395.  
  396. #ifdef AIX3
  397.  /* we later go through the relocation entries making this 1
  398.     for symbols used */
  399. #ifdef SYM_USED 
  400.  if(TC_SYMBOL_P(sym))
  401.    {SYM_USED(sym) = 0;}
  402. #endif
  403.  
  404.  /* fix up the external refer to _ptrgl to be local ref */
  405.  if (sym->n_scnum == 0 &&
  406.      strcmp(sym->n_name,"_ptrgl")==0)
  407.    {struct syment* s =
  408.       get_symbol("._ptrgl",TEXT_NSCN,symbol_table,length);
  409.     if (s ==0) FEerror("bad glue",0);
  410.     sym->n_value = next_bss ;
  411.     ptrgl_offset = next_bss;
  412.     ptrgl_text = s->n_value;
  413.     next_bss += 0xc;
  414.     sym->n_scnum = DATA_NSCN;
  415.     ((union auxent *)(sym+1))->x_csect.x_scnlen = 0xc;
  416.  
  417.   }
  418.  
  419.      if(sym->n_scnum != BSS_NSCN) goto NEXT;
  420.      if(SYM_EXTERNAL_P(sym))
  421.        {int val=sym->n_value;
  422.     struct node joe;
  423.     if (val && c_table.ptable)
  424.       {struct node *answ;
  425.        answ= find_sym(sym,0);
  426.            if(answ)
  427.          {sym->n_value = answ->address ;
  428.           sym->n_scnum = N_UNDEF;
  429.           val= ((union auxent *)(sym+1))->x_csect.x_scnlen;
  430.           result -= val;
  431.           goto NEXT;
  432.         }}
  433.       }
  434.  /* reallocate the bss space */
  435.  if (sym->n_value == 0)
  436.    {result += ((union auxent *)(sym+1))->x_csect.x_scnlen;}
  437.  sym->n_value = next_bss;
  438.  next_bss += ((union auxent *)(sym+1))->x_csect.x_scnlen;
  439.  NEXT:
  440.  ;
  441.      /* end aix3 */
  442. #endif
  443.       
  444.  
  445.   
  446. #ifdef BSD
  447.      tem; /* ignored */
  448.      if(SYM_EXTERNAL_P(sym) && SYM_UNDEF_P(sym))
  449. #endif
  450. #ifdef COFF
  451.      if(0)
  452.      /* what we really want is
  453.     if (sym->n_scnum==0 && sym->n_sclass == C_EXT
  454.                         && !(bsearch(..in ptable for this symbol)))
  455.     Since this won't allow loading in of a new external array
  456.     char foo[10]  not ok
  457.     static foo[10] ok.
  458.     for the moment we give undefined symbol warning..
  459.     Should really go through the symbols, recording the external addr
  460.     for ones found in ptable, and for the ones not in ptable
  461.     set some flag, and add up the extra_bss required.  Then
  462.     when you have the new memory chunk in hand,
  463.     you could make the pass setting the relative addresses.
  464.     for the ones you flagged last time.
  465.     */
  466. #endif
  467.        /* external bss so not included in size of bss for file */
  468.        {int val=sym->n_value;
  469.     if (val && c_table.ptable
  470.         && (0== find_sym(sym,0)))
  471.        { sym->n_value=result;
  472.          result += val;}}
  473.      
  474.      sym += NUM_AUX(sym); 
  475.  
  476.    }
  477.  return (result-start);
  478. }
  479.  
  480.  
  481.  
  482. /* go through the symbol table changing the addresses of the symbols
  483. to reflect the current cfd_start */
  484.  
  485.  
  486.  
  487. relocate_symbols(length)
  488. unsigned int length;
  489. {struct syment *end,*sym;
  490.  unsigned int typ;
  491.  char *str;
  492.  char tem[SYMNMLEN +1];
  493.  tem[SYMNMLEN]=0;
  494.  end =symbol_table + length;
  495.  for(sym=symbol_table; sym < end; sym++) {
  496.     typ=NTYPE(sym);
  497. #ifdef BSD
  498. #ifdef N_STAB    
  499.     if (N_STAB & sym->n_type) continue;/* skip: It  is for dbx only */
  500. #endif    
  501.     typ=N_SECTION(sym);
  502. /* if(sym->n_type  &  N_EXT) should add the symbol name,
  503.    so it would be accessible by future loads  */
  504. #endif
  505.    switch (typ)    {
  506. #ifdef BSD
  507.    case N_ABS : case N_TEXT: case N_DATA: case N_BSS:
  508. #endif
  509. #ifdef COFF
  510.    case TEXT_NSCN : case DATA_NSCN: case BSS_NSCN :
  511. #endif
  512.      str=SYM_NAME(sym);
  513.      dprintf( for sym %s ,str)
  514.      dprintf( new value will be start %x, start_address);
  515.  
  516. #ifdef AIX3 
  517.      if(N_SECTION(sym) == DATA_NSCN
  518.     && NUM_AUX(sym) 
  519.     && allocate_toc(sym))
  520.        break;
  521. #endif     
  522.        sym->n_value = (int)start_address;
  523.      break;
  524.    case  N_UNDEF:
  525.      str=SYM_NAME(sym);
  526.      dprintf( undef symbol %s ,str);    
  527.      dprintf( symbol diff %d , sym - symbol_table);
  528.      describe_sym(sym-symbol_table);
  529.      set_symbol_address(sym,str);
  530.      describe_sym(sym-symbol_table);
  531.      break;
  532.    default:
  533. #ifdef COFF
  534.      dprintf(am ignoring a scnum %d,(sym->n_scnum));
  535. #endif
  536.      break;
  537.    }
  538.    sym += NUM_AUX(sym);
  539.  }
  540. }
  541.  
  542. /* 
  543. STEPS:
  544. 1) read in the symbol table from the file,
  545. 2) go through the symbol table, relocating external entries.
  546. 3) for i <=2 go thru the relocation information for this section
  547.  relocating the text.
  548. 4) done.
  549. */
  550.  
  551. struct node *
  552. find_sym(sym,name)
  553.   struct syment *sym;
  554.    char *name;
  555. { char tem[SYMNMLEN +1];
  556.   tem [SYMNMLEN] = 0;
  557.   if (name==0) name = SYM_NAME(sym);
  558.   return find_sym_ptable(name);}
  559.  
  560. set_symbol_address(sym,string)
  561. struct syment *sym;
  562. char *string;
  563. {struct node *answ;
  564.  if (c_table.ptable)
  565.     {
  566.      dprintf(string %s, string);
  567.     answ = find_sym(sym,string);
  568.      dprintf(answ %d , (answ ? answ->address : -1));
  569.     if(answ)
  570.      {
  571. #ifdef COFF
  572. #ifdef _AIX370
  573.      if (NTYPE(sym) == N_UNDEF)   
  574.        sym->n_value = answ->address;
  575.      else 
  576. #endif 
  577.       sym->n_value = answ->address -sym->n_value;
  578.       /* for symbols in the local  data,text and bss this gets added
  579.      on when we add the current value */
  580. #endif
  581. #ifdef BSD
  582.       /* the old value of sym->n_value is the length of the common area
  583.      starting at this address */
  584.       sym->n_value = answ->address;
  585. #endif
  586. #ifdef AIX3
  587.      fix_undef_toc_address(answ,sym,string);
  588. #endif
  589.       
  590. }      
  591.      else
  592.       {
  593. /*
  594. #ifdef BSD
  595.     {char *name;
  596.      name=malloc(1+strlen(string));
  597.      strcpy(name,string);
  598.      sym->n_value = sym->n_value + (unsigned int) the_start;
  599.      add_symbol(name,sym->n_value,NULL);
  600.        }
  601. #endif
  602. */
  603.      fprintf(stdout,"undefined %s symbol",string)
  604.       ;fflush(stdout);
  605.      
  606.    }}
  607.  
  608.     else{FEerror("symbol table not loaded",0,0);}}
  609.  
  610. /* include the machine independent stuff */
  611. #include "sfasli.c"
  612.  
  613.  
  614. #ifdef DEBUG
  615. print_name(p)
  616.      struct syment *p;
  617. {char tem[10],*name;
  618.  name=SYM_NAME(p);
  619.  name=   (((p)->_n._n_n._n_zeroes == 0) ? 
  620.         &my_string_table[(p)->_n._n_n._n_offset] :
  621.                ((p)->_n._n_name[SYMNMLEN -1] ? 
  622.                  (strncpy(tem,(p)->_n._n_name,  
  623.                        SYMNMLEN), 
  624.                   (char *)tem) : 
  625.                   (p)->_n._n_name ));
  626.  
  627.  printf("(name:|%s|)",name);
  628.  printf("(sclass 0x%x)",p->n_sclass);
  629.   printf("(external_p 0x%x)",SYM_EXTERNAL_P(p));
  630.  printf("(n_type 0x%x)",p->n_type);
  631.  printf("(n_value 0x%x)",p->n_value);
  632.  printf("(numaux 0x%x)\n",NUM_AUX(p));
  633.  fflush(stdout);
  634. }
  635. #endif
  636.  
  637. #endif /* SEPARATE_SFASL_FILE */
  638.